import base64
import hashlib
import oauth
import urllib

from Crypto.PublicKey import RSA
from Crypto.Util import number
import logging

#MIXI_CERT = "0xC048F9DD595072FD561EF7D69533FE4F5957520F755BE6E0252B870" \
#            "03F3D3DD55FF548E78BDD8491B8EA68B0F3038DFE53950B94AFF4E634" \
#           "4E9C6C050557484B150B81EBD2A624DF81B7C270A6D15BB857AD34A68" \
#            "C5444A7B60EBDF953DEBAFBAAA36F8E6FB75C4D79EF3714DF74973081" \
#            "AF5F5B901FF6387CDA44135A665FE5"

MIXI_CERT = "B5BAB9467B3920492D5E5759FB7EC58E56AF9EE73826EC2B0F817EE0" \
            "D43057056D479CB0560D7411A9D759218801B505C7A865A6960E6F4C" \
            "7FDCF04C1BCD3AE372E65D2266BEFE1589150197662CF487B62FF0FD" \
            "2954170D68098F1046AA8E4C3BAAC0FC8A7BF246E235B210254209B5" \
            "BB896562F72CC55EEA6A483B64948B55"



def signed_request(fn):
    def verify(self, *args, **kw):
        # Construct a RSA.pubkey object
        exponent = 65537
        public_key_long = long(MIXI_CERT, 16)
        public_key = RSA.construct((public_key_long, exponent))

        try:
            # Rebuild the message hash locally
            oauth_request = oauth.OAuthRequest(
                http_method=self.request.method, 
                http_url=self.request.url, 
                parameters=self.request.params.mixed())
            message = '&'.join((
                oauth.escape(oauth_request.get_normalized_http_method()),
                oauth.escape(oauth_request.get_normalized_http_url()),
                oauth.escape(oauth_request.get_normalized_parameters()),
                ))
            local_hash = hashlib.sha1(message).digest()

            # Apply the public key to the signature from the remote host
            sig = base64.decodestring(
                urllib.unquote(self.request.params.mixed()["oauth_signature"]))
            remote_hash = public_key.encrypt(sig, '')[0][-20:]
            logging.getLogger().setLevel(logging.DEBUG)
            logging.debug("local_hash:"+local_hash+" remote_hash:"+remote_hash)
            # Verify that the locally-built value matches the value
            # from the remote server
            if local_hash != remote_hash:
                raise

            return fn(self, *args, **kw)

        except oauth.OAuthError, err:
            self.response.set_status(401)
            self.response.out.write(err.message)
        except:
            self.response.set_status(401)
            self.response.out.write('Invalid OAuth Signature.')

    return verify
